#pragma once


#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QVector3D>
#include <QMatrix4x4>
#include <QMutex>
#include <QVector>
#include <QMap>
#include "OpenGLCamera.h"
#include <QOpenGLExtraFunctions>
#include <memory>
class QOpenGLVertexArrayObject;
class OpenGLCamera;


class QOpenglMeshObj
{
public:
	QOpenglMeshObj() :
		m_bufferVertData(QOpenGLBuffer::Type::VertexBuffer),
		m_bufferIndex(QOpenGLBuffer::IndexBuffer)
	{
		m_iPntSize = 0;
	}

	void Bind()
	{
		m_bufferVertData.bind();
		m_bufferIndex.bind();

	}

	void UnBind()
	{
		m_bufferVertData.release();
		m_bufferIndex.release();
	}

	void LoadGeneralObj(const QVector<QVector3D>& vPnt, const QVector<QVector3D>& vNormal, const QVector<QVector3D>& vColor, const QVector<int>& vInx, int iTypeDraw);

	int GetPntSize()
	{
		return m_iPntSize;
	}

	int GetIndexSize()
	{
		return m_iInxSize;
	}

	int GetTypeDraw() const { return m_iTypeDraw; }
private:
	QOpenGLBuffer m_bufferVertData, m_bufferIndex;
	int m_iTypeDraw;
	int m_iPntSize;
	int m_iInxSize;
#ifdef DEBUG
	QVector<QVector3D> m_vPnt;
#endif
};

class QOpenglGemo
{
public:
	QOpenglGemo()
	{
		m_bIsEnableClip = false;
	};
	QOpenglGemo(std::shared_ptr<QOpenglMeshObj> pMesh, QOpenGLShaderProgram* pShader, QMatrix4x4 transform);

	void Draw(QOpenGLExtraFunctions *f, const QMatrix4x4& matCamera, const QMatrix4x4& matParent, const QMatrix4x4& matProj);

	void SetClipPlane(bool bEnable = true, QVector4D plane = QVector4D(0, 0, 1, -1));
protected:
	virtual void BeginDraw(QOpenGLExtraFunctions *f, const QMatrix4x4& matCamera, const QMatrix4x4& matParent, const QMatrix4x4& matProj);
	virtual void DrawCore(QOpenGLExtraFunctions *f);
	virtual void EndDraw(QOpenGLExtraFunctions *f);
protected:
	std::shared_ptr<QOpenglMeshObj> m_pMesh;
	QOpenGLShaderProgram* m_pShader;
	QMatrix4x4 m_transform;
	bool m_bIsEnableClip;
	QVector4D m_vePlane;
};

class QOpenglFromOpengl : public QOpenGLWidget, protected QOpenGLFunctions
{

public:
	QOpenglFromOpengl(QWidget*pParent) :QOpenGLWidget(pParent)
	{
		SetCanMove(true);
	}
	void SetCanMove(bool val) { m_isCanMove = val; }

	void AddGeneralMesh(QString strMeshName, const QVector<QVector3D>& vPnt, const QVector<QVector3D>& vNormal, const QVector<QVector3D>& vColor, const QVector<int>& vInx, int iTypeDraw);
protected:
	void AddGemo(int gemoType, QString strMeshName, QMatrix4x4 transform, QVector3D fColor = QVector3D(), int iUseColor = 0);
	void paintGL() override;
	void Draw(GLenum mode);
	virtual void initializeGL();
	virtual void resizeGL(int width, int height);
	QString GetFileData(const QString& strFileName) const;
	virtual void keyPressEvent(QKeyEvent *);
	virtual void mousePressEvent(QMouseEvent *);
	virtual void mouseReleaseEvent(QMouseEvent *);
	virtual void mouseMoveEvent(QMouseEvent *);
	virtual void mouseDoubleClickEvent(QMouseEvent*);
	virtual void ClearAll();

	void SelectObject(int x, int y);
protected:
	QVector<std::pair<int, std::shared_ptr<QOpenglGemo>>> m_vGemoObj;
	QMap<QString, std::shared_ptr<QOpenglMeshObj>> m_vMeshObj;
	QOpenGLShaderProgram* m_pProgram;
	OpenGLCamera m_camera;
	QMutex m_MutexLock;
	QPoint m_pntFrom;
	QMatrix4x4 m_proj;
	bool m_isCanMove;
};

class QOpenglColorGemo :public QOpenglGemo
{
public:
	QOpenglColorGemo() {};
	QOpenglColorGemo(std::shared_ptr<QOpenglMeshObj> pMesh, QVector3D fColor, QOpenGLShaderProgram* pShader, QMatrix4x4 transform) :QOpenglGemo(pMesh, pShader, transform)
	{
		m_fColor = fColor;
	};
protected:
	void BeginDraw(QOpenGLExtraFunctions *f, const QMatrix4x4& matCamera, const QMatrix4x4& matParent, const QMatrix4x4& matProj)
	{
		QOpenglGemo::BeginDraw(f, matCamera, matParent, matProj);
		m_pShader->setUniformValue("useColor", 1);
		m_pShader->setUniformValue("color", m_fColor);
	};
private:
	QVector3D m_fColor;
};